Flutter UiKitView 嵌入iOS原生View 您所在的位置:网站首页 flutter 调用原生view Flutter UiKitView 嵌入iOS原生View

Flutter UiKitView 嵌入iOS原生View

2023-05-07 11:53| 来源: 网络整理| 查看: 265

本篇文章 中写到的是 flutter 通过 UiKitView 调用了ios 原生的 UILabel 案例。

flutter 通过AndroidView 调用android 原生的TextView 请点击查看这里

flutter 中嵌套使用ios原生组件的流程基本上可以描述为:

1 info.plist文件设置2 ios 端实现原生组件PlatformView提供原生view3 ios 端创建PlatformViewFactory用于生成PlatformView4 ios 端创建FlutterPlugin用于注册原生组件5 flutter 平台嵌入 原生view1 info.plist文件设置

iOS端的UiKitView目前还只是preview状态, 默认是不支持的, 需要手动打开开关, 在info.plist文件中新增一行io.flutter.embedded_views_preview为true.

如果不添加,会抛出如下异常:

Trying to embed a platform view but the PrerollContext does not support embedding

Flutter UiKitView 嵌入iOS原生View_flutter

2 创建IOS 原生View

创建类 FlutterIosTextLabel 并实现FlutterPlatformView 协议

FlutterIosTextLabel.h

#import #import

NS_ASSUME_NONNULL_BEGIN

//实现协议FlutterPlatformView@interface FlutterIosTextLabel : NSObject

-(instancetype)initWithWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args binaryMessenger:(NSObject*)messenger;@end

NS_ASSUME_NONNULL_END

FlutterIosTextLabel.m

#import "FlutterIosTextLabel.h"

@implementation FlutterIosTextLabel{ //FlutterIosTextLabel 创建后的标识 int64_t _viewId; UILabel * _uiLabel; //消息回调 FlutterMethodChannel* _channel;}

//在这里只是创建了一个UILabel-(instancetype)initWithWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger{ if ([super init]) { if (frame.size.width==0) { frame=CGRectMake(frame.origin.x, frame.origin.y, [UIScreen mainScreen].bounds.size.width, 22); } _uiLabel =[[UILabel alloc] initWithFrame:frame]; _uiLabel.textColor=[UIColor redColor]; _uiLabel.text=@"ios 原生 uilabel "; _uiLabel.font=[UIFont systemFontOfSize:14]; _uiLabel.textAlignment=NSTextAlignmentCenter; _uiLabel.backgroundColor=[UIColor grayColor];

_viewId = viewId;

} return self;

}

- (nonnull UIView *)view { return _uiLabel;}

@end

2 创建PlatformViewFactory

FlutterIosTextLabelFactory.h

#import #import NS_ASSUME_NONNULL_BEGIN

@interface FlutterIosTextLabelFactory : NSObject

- (instancetype)initWithMessenger:(NSObject*)messager;

@end

NS_ASSUME_NONNULL_END

FlutterIosTextLabelFactory.m

#import "FlutterIosTextLabelFactory.h"#import "FlutterIosTextLabel.h"

@implementation FlutterIosTextLabelFactory{ NSObject*_messenger;}- (instancetype)initWithMessenger:(NSObject *)messager{ self = [super init]; if (self) { _messenger = messager; } return self;}

//设置参数的编码方式 -(NSObject *)createArgsCodec{ return [FlutterStandardMessageCodec sharedInstance];}

//用来创建 ios 原生view- (nonnull NSObject *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { //args 为flutter 传过来的参数 FlutterIosTextLabel *textLagel = [[FlutterIosTextLabel alloc] initWithWithFrame:frame viewIdentifier:viewId arguments:args binaryMessenger:_messenger]; return textLagel;}

@end

4 创建Plugin

FlutterIosTextLabelPlugin.h

#import #import

NS_ASSUME_NONNULL_BEGIN

@interface FlutterIosTextLabelPlugin :NSObject

@end

NS_ASSUME_NONNULL_END

FlutterIosTextLabelPlugin.m

#import "FlutterIosTextLabelPlugin.h"#import "FlutterIosTextLabelFactory.h"

@implementation FlutterIosTextLabelPlugin

+ (void)registerWithRegistrar:(nonnull NSObject *)registrar {

//注册插件 //注册 FlutterIosTextLabelFactory //com.flutter_to_native_test_textview 为flutter 调用此 textLabel 的标识 [registrar registerViewFactory:[[FlutterIosTextLabelFactory alloc] initWithMessenger:registrar.messenger] withId:@"com.flutter_to_native_test_textview"];}

@end

4 注册4.1 创建 FlutterIosTextLabelRegistran

FlutterIosTextLabelRegistran.h

#import #import #import "FlutterIosTextLabelPlugin.h"NS_ASSUME_NONNULL_BEGIN

@interface FlutterIosTextLabelRegistran : NSObject+ (void)registerWithRegistry:(NSObject*)registry;@end

NS_ASSUME_NONNULL_END

FlutterIosTextLabelRegistran.m

#import "FlutterIosTextLabelRegistran.h"

@implementation FlutterIosTextLabelRegistran

+(void)registerWithRegistry:(NSObject *)registry{ //注册插件 [FlutterIosTextLabelPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterIosTextLabelPlugin"]];}

@end

4.2 AppDelegate 中注册插件import UIKitimport Flutter

@UIApplicationMain@objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { //flutter 中引用的插件通过些类来注册 GeneratedPluginRegistrant.register(with: self); ... .. //注册插件 FlutterIosTextLabelRegistran.register(with: self); return super.application(application, didFinishLaunchingWithOptions: launchOptions) }}

5 flutter页面中使用UiKitView嵌入ios 原生UILabel5.1 最简单的调用

Flutter UiKitView 嵌入iOS原生View_flutter 调用原生view_02

//这里设置的 viewType值与 ios 中插件注册的标识 一至// [registrar registerViewFactory:[[FlutterIosTextLabelFactory alloc] initWithMessenger:registrar.messenger] withId:@"com.flutter_to_native_test_textview"];@override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: appBar, //显示的页面 body: Container( height: 200, child: UiKitView( //设置标识 viewType: "com.flutter_to_native_test_textview", ), ), ); }5.2 flutter 调用 原生view并传参数Flutter UiKitView 嵌入iOS原生View_flutter 调用ios原生view_03mTextWidget = Container( height: 200, child: UiKitView( //标识 viewType: "com.flutter_to_native_test_textview", creationParams: { "content": "flutter 传入的文本内容", }, //参数的编码方式 creationParamsCodec: const StandardMessageCodec(), ), );

ios 原生中的接收(只会接收一次)

#import "FlutterIosTextLabel.h"

@implementation FlutterIosTextLabel{ //FlutterIosTextLabel 创建后的标识 int64_t _viewId; UILabel * _uiLabel; //消息回调 FlutterMethodChannel* _channel;}

-(instancetype)initWithWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger{ if ([super init]) {

.... .... //接收 初始化参数 NSDictionary *dic = args; NSString *content = dic[@"content"]; if (content!=nil) { _uiLabel.text=content; }

.... .... } return self;

}

... ...

@end

5.3 flutter 更新 原生view 中的数据

原生组件初始化的参数并不会随着setState重复赋值,可以通过MethodCall来实现更新数据。

首先让原生view组件实现MethodCallHandler接口:

在FlutterIosTextLabel 的初始化函数中

-(instancetype)initWithWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger{ if ([super init]) {

... ...

// 注册flutter 与 ios 通信通道 NSString* channelName = [NSString stringWithFormat:@"com.flutter_to_native_test_textview_%lld", viewId]; _channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger]; __weak __typeof__(self) weakSelf = self; [_channel setMethodCallHandler:^(FlutterMethodCall * call, FlutterResult result) { [weakSelf onMethodCall:call result:result]; }];

} return self;

}

-(void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result{ if ([[call method] isEqualToString:@"updateText"]) { //获取参数 NSDictionary *dict = call.arguments; NSString *content = dict[@"updateText"]; if (content!=nil) { _uiLabel.text=content; } }else{ //其他方法的回调 }}

flutter 中调用 ios 原生view

MethodChannel _channel; int viewId=0;mTextWidget = Container( height: 200, child: AndroidView( //标识 viewType: "com.flutter_to_native_test_textview", creationParams: { "content": "flutter 传入的文本内容", }, //参数的编码方式 creationParamsCodec: const StandardMessageCodec(), //view创建完成时的回调 onPlatformViewCreated: (id) { viewId = id; }, ), );

更新数据

//这里设置的标识 MethodChannel('com.flutter_to_native_test_textview_$viewId');// 与ios NSString* channelName = [NSString stringWithFormat:@"com.flutter_to_native_test_textview_%lld", viewId]; 中注册的一至void clickUpdtae(){_channel = new MethodChannel('com.flutter_to_native_test_textview_$viewId'); updateTextView();}

//这里的标识 updateText//与android 中接收消息的方法中//if ("updateText".equals(methodCall.method)) {...} 一至void updateTextView() async { return _channel.invokeMethod('updateText', "更新内容"); }

通过onPlatformViewCreated回调,监听原始组件成功创建,并能够在回调方法的参数中拿到当前组件的id,这个id是系统随机分配的,然后通过这个分配的id加上我们的组件名称最为前缀创建一个和组件通讯的MethodChannel,拿到channel对象之后就可以通过invokeMethod方法向原生组件发送消息了,这里这里调用的是‘updateText’这个方法,参数是一个String.

本公众号会首发系列专题文章,付费的视频课程会在公众号中免费刊登,在你上下班的路上或者是睡觉前的一刻,本公众号都是你浏览知识干货的一个小选择,收藏不如行动,在那一刻,公众号会提示你该学习了。

Flutter UiKitView 嵌入iOS原生View_flutter 调用ios原生view_04



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有